package com.wanmait.demo;

import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

@Configuration
public class shiroConfiguration {
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {

        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);
        //登陆界面
        bean.setLoginUrl("/adminlogin1");
        //成功后页面
        bean.setSuccessUrl("/manage/index");
        //无权限后的页面
        bean.setUnauthorizedUrl("/unauthorized");
        //键值对:请求-拦截器(权限配置)
        LinkedHashMap<String, String> filterChainDefinitonMap = new LinkedHashMap<>();
        //首页地址index，使用authc过滤器进行处理
        filterChainDefinitonMap.put("/manage/index", "authc");
        //登陆不需要任何过滤
        filterChainDefinitonMap.put("/adminlogin", "anon");

        //只有角色中拥有admin才能访问admin
        filterChainDefinitonMap.put("/manage/admin", "roles[admin]");
        //拥有edit权限
        filterChainDefinitonMap.put("/manage/admin/list", "perms[admin]");
        //druid
        filterChainDefinitonMap.put("/druid/**", "anon");
        //其他请求只验证是否登陆过
        filterChainDefinitonMap.put("/manage/**", "user");
        //放入Shiro过滤器
        bean.setFilterChainDefinitionMap(filterChainDefinitonMap);
        return bean;
    }


    @Bean("securityManager")
    //public SecurityManager securityManager(@Qualifier("dbRealm") DbRealm dbRealm,@Qualifier("cacheManager") CacheManager cacheManager){
    public SecurityManager securityManager(DbRealm dbRealm,EhCacheManager ehCacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(ehCacheManager);
        securityManager.setRealm(dbRealm);
        return securityManager;
    }

    @Bean("dbRealm")
    public DbRealm dbRealm(CredentialsMatcher credentialsMatcher) {

        DbRealm dbRealm = new DbRealm();
        //信息放入缓存
        //dbRealm.setCacheManager(new MemoryConstrainedCacheManager());
        //dbRealm.setAuthenticationCacheName("authenticationCache");
//        dbRealm.setAuthorizationCacheName("authorizationCache");

       dbRealm.setCredentialsMatcher(credentialsMatcher);
        return dbRealm;
    }

    //shiro集成EhCache,但是没有交给spring去管理缓存，如果spring也使用ehcache则会出错

   @Bean
    public EhCacheManager ehCacheManager(CacheManager cacheManager){
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }



    @Bean
    public CredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        credentialsMatcher.setHashIterations(2);
        //credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }


    //启用controller的权限注解
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {

        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }

    // 开启代理 不开启的话权限注解不起作用
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
}
